#ifndef	_J_STRANICENJE_H_
#define	_J_STRANICENJE_H_

#include "razno.h"
#include "postavke.h"

void j_inicijaliziraj_stranicenje ();

void j_inicijaliziraj_stranice_za_proces ( int proces_id,
					   void *pocetna_adresa,
					   aint velicina,
					   bool u_jezgri, bool stranicenje );

//pretvaranje adrese iz logickog prostora (procesa) u apsulutnu adresu (jezgra)
int j_adresa_u_jezgri (	void *adr_u_procesu, void **adr_u_jezgri,
			void *spremnik );

void j_prekid_zbog_promasaja ( int id, void *param );

void j_kopiraj_u_ili_iz_procesa ( void *_adr_u_jezgri, void *_adr_u_proc,
					 aint velicina, void *_spremnik,
					 uint zast );

void j_oslobodi_spremnicki_prostor ( void *_spremnik );


#if	defined(_J_SPREMNIK_C_) || defined(_J_STRANICENJE_C_) || 	\
	defined(_J_PROCESI_C_) || defined(_ARH_KONTEKST_C_)

#include <arh/spremnik.h>

/*
//mapa spremnika - predvidjeno za jezgru
typedef struct _j_mapa_spremnika_t_ {
	void *pocetak;	//pocetak segmenta
	uint velicina;	//velicina segmenta
	uint zast;	//za sto se koristi
	struct _j_mapa_spremnika_t_ *iduci;
} j_mapa_spremnika_t;
*/

//mapa spremnika za proces, sto je zauzeto/rezervirano i s kakvim zastavicama
typedef struct _j_segment_t_ 
{
	void *pocetak;	//pocetak segmenta
	void *kraj;	//prva adresa izvan segmenta
	void *ucitaj_od;//apsolutna adresa od kuda ucitati
	uint zast; //razne zastavice, npr. citaj/pisi/kod/stog/gomila
	struct _j_segment_t_ *iduci;

} j_segment_t;

//za ostvarenje liste segmenata
typedef struct _j_lista_segmenata_t_
{
	j_segment_t *prvi;
	j_segment_t *zadnji;

} j_lista_segmenata_t;

#define USPOREDI_SEGMENTE(a, b)	\
	( ( (aint) (a)->pocetak ) - ( (aint) (b)->pocetak ) )


//u sustavu stranicenja, adresa stranice se dijeli na najvise tri dijela koji
//sluze za izgradnju hijerarhijskog stabla stranica
//logicka adresa: [ dio1 : dio2 : dio3	: pomak_u_stranici ]
//fizicka adresa: [ adresa_okvira       : pomak_u_okviru   ]

typedef union _j_adresa_t_ {
	struct _adresa_t_ {
		aint p : POMAK;	//pomak od pocetka stranice/okvira

		#if IMA_IND_2
		#if IMA_IND_3

		aint i3 : VEL_IND_3;	//indeks trece razine

		#endif

		aint i2 : VEL_IND_2;	//indeks druge razine

		#endif // IMA_IND_2

		aint i1 : VEL_IND_1;	//indeks prve razine

	} __attribute__((__packed__)) ind;

	aint adr;

} j_adresa_t;


//element tablice stranica - ili pokazuje izravno na stranicu s podacima ili na
//drugu tablicu nize razine
typedef struct _j_tabstr_t_ {
	aint zast : POMAK;	//zastavice

	aint ind : VEL_IND;	//kazaljka na "granu"

} __attribute__((__packed__)) j_tabstr_t;

#include "spremnik.h"

//okvir
typedef uint8 j_okvir_t[VEL_STRANICE];

//pretvaranje iz "j_tabstr_t" u broj
#define	U_INT(str)	( (str).zast | ( (str).ind << POMAK ) )


//makroi za oznacavanje i trazenje slobodnog okvira

#define OZNACI_OKVIR_SLOBODAN( ELEMENT )	\
obradi_bit_32 ( mj_okvir, br_okvira, ELEMENT, MPOSTAVI )

#define OZNACI_OKVIR_ZAUZET( ELEMENT )	\
obradi_bit_32 ( mj_okvir, br_okvira, ELEMENT, MOBRISI )

#define DOHVATI_PRVI_SLOBODAN_OKVIR()	\
pronadji_bit_32 ( mj_okvir, br_okvira, ISTINA )


//zastavice za "j_dodaj_procesu" (pridjeljuju se segmentima procesa)
#define	KOPIRAJ		(1<<0)	//napuni stranicu podacima kopiranjem
#define	MAPIRAJ		(1<<1)	//samo azuriraj tablicu, mapira se postojece
#define	PRAZNO		(1<<2)	//nova stranica ce biti prazna
#define	STVORI		(1<<3)	//stvori ako ne postoji
#define	SAMO_REZERVIRAJ	(1<<4)	//samo rezerviraj prostor (u opisniku mape
				//procesa, ne i u tablicama prevodjenja!)

#define	U_PROCES	(1<<5)	//kopira se iz jezgre u proces
#define	U_JEZGRU	(1<<6)	//kopira se iz procesa u jezgru

#define	SAMO_ZA_CITANJE	(1<<7)	//stranica je samo za citanje (npr. kod)
#define	ZA_JEZGRU	(1<<8)	//smije se koristiti samo u prihvatu prekida
#define	ZA_PROCES	(1<<9)	//smije se koristiti i iz programa

#define	ZA_TABLICU	(1<<10)	//pokazuje na tablicu sa pokazivacima!

#endif	/* _J_SPREMNIK_C_ || _J_STRANICENJE_C_ || _J_PROCESI_C_ */

#ifdef	_J_STRANICENJE_C_

//lokalne "pomocne funkcije"

static bool j_sredi_stranicu ( void *adresa, void *_spremnik );

static void j_dodaj_procesu (	void *adr_u_jezgri, void *adr_u_proc,
				aint velicina, void *spremnik, uint zast );

static void j_kopiraj_u_ili_iz_stranice ( void **adr_u_jezgri,
					  void **adr_u_proc,
					  aint *velicina, void *spremnik,
					  void *stranica, uint zast );

static j_tabstr_t j_uzmi_prazni_okvir ();

static void j_provjeri_i_dohvati ( void *_stranica, uint zast, 
				   void *adr_u_proc, void *adr_u_jezgri,
				   void *spremnik );

static void *j_provjeri_adresu ( void *adr_u_proc, void *_spremnik );

static void *j_dohvati_opisnik_stranice ( void *adresa, void *_spremnik );

static void j_dodaj_u_adrese_procesa ( void *adr_u_proc, void *adr_u_jezgri,
			        aint velicina, void *_spremnik, uint zast );


static void j_oslobodi_stranicu ( void *stranica );

static uint j_makni_iz_adresa_procesa ( void *adr_u_proc, aint velicina,
					void *_spremnik );

void j_makni_iz_procesa ( void *adr_u_proc, aint velicina, void *_spremnik );


void j_prikazi_tablicu ( void *pocetak, int br_zapisa );

void j_prikazi_translacije ( aint pocetak, aint adresa );

static inline void *j_dohvati_adresu_promasaja ()
{
	return arh_dohvati_adresu_promasaja ();
}

#endif	/* _J_STRANICENJE_C_ */
#endif	/* _J_STRANICENJE_H_ */
